﻿using System.Collections;
using System.Collections.Generic;

namespace CoAnimator
{
    public abstract class CoScript
    {
        Stack<IEnumerator> mScript;

        /// <summary>
        /// Overload this method to store your script but never actually call it yourself, use
        /// Start() and Resume() instead. 'yield return true' and 'yield return false' both
        /// pause execution until the next time Resume() is called. yield break ends the script
        /// and clears its memory. yield break inside a method clears the methods memory and
        /// returns to the calling method.
        /// </summary>
        /// <returns>nothing of consequence</returns>
        public abstract IEnumerable Script();

        /// <summary>
        /// Start the script over from the beginning clearing all memory
        /// </summary>
        /// <returns>true if the script finishes as soon as its started</returns>
        public bool Start()
        {
            mScript = new Stack<IEnumerator>();
            mScript.Push(Script().GetEnumerator());
            return Resume();
        }

        /// <summary>
        /// Resume the script from the last yield
        /// </summary>
        /// <returns>true if the script finishes</returns>
        public bool Resume()
        {
            if (mScript == null)
                return Start();

            if (mScript.Count == 0)
                return true;

            if (!mScript.Peek().MoveNext())
            {
                mScript.Pop();
                Resume();
            }

            if (mScript.Count == 0)
                return true;

            if (mScript.Peek().Current is IEnumerable)
            {
                mScript.Push(((IEnumerable)mScript.Peek().Current).GetEnumerator());
                Resume();
            }


            return mScript.Count == 0;
        }
    }
}
